﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Timers;
using System.IO.Ports;
using SensorMash;
using PubSubPublisher;

namespace SensorMashUI
{
    public partial class UI : Form
    {
        // This delegate enables asynchronous calls for setting
        // the text property on a Label control.
        private delegate void SetTextCallback(string text, Label label);
        private delegate void SetTextBoxCallback(string text, TextBox txtbox);
        private delegate void SetCheckBoxCallback(bool check, CheckBox cbo, string varName);
        private delegate void SetCheckListBoxCallback(int pos, CheckedListBox clbo, bool check, string varName);
        private delegate void SetProgressBarCallback(int val);
        private delegate void SetCboTextCallback(string text, CheckBox cbo, string varName);
        
        private delegate void UpdateSensorStateDelegate(SensorMashChangedEventArgs args);

        private System.Timers.Timer timer;
        private double timerInterval = 500; //0.5 seconds
        private string PubServiceIPAddress;
        private int PubServicePortNo;

        private Bitmap b = new Bitmap(256, 192, PixelFormat.Format24bppRgb);
        private Graphics g;

        WiimoteData wiiD;
        RawWiimoteVars wiiVars;
        //RawNunchukVars nunchukVars;
        private Dictionary<string, object> wiiVarsTable;

        private bool isStreaming = false;
        private bool timedStreaming = false; //timer elapsed will switch true/false 
        private Publisher pub;


        /// <summary>
        /// Set up for Arduino serial communication connectivity
        /// </summary>
        private string portName = "COM17";
        private int baudRate = 9600;
        private SerialPort serialPort;

        public UI()
        {
            InitializeComponent();

            
            timer = new System.Timers.Timer();
            if (txtInterval.Text != null && txtInterval.Text != "")
            {
                timerInterval = Convert.ToDouble(txtInterval.Text);
            }
            timer.Interval = timerInterval; 
            timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
            timer.Enabled = false;
            timer.AutoReset = true;
        }

        private void timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            if (timedStreaming)
                timedStreaming = false;
            else
                timedStreaming = true;
            /*
            //try
            //{
                lock (this)
                {
                    if (isStreaming)
                    {
                        foreach (KeyValuePair<string, object> kvp in wiiVarsTable)
                        {
                            if (kvp.Value != null)
                                pub.SendASingleData(txtWiiPrefix.Text + kvp.Key, kvp.Value.ToString());//else
                        }
                                //if (kvp.Key != "Roll")
                                    //pub.SendASingleData("WII|" + kvp.Key, kvp.Value.ToString());

                                
                                //{
                                //    double roll = Math.Round((double)wiiVarsTable["Roll"], 2);
                                //    double change = Math.Abs(Math.Abs(roll) - Math.Abs(prevRoll));

                                //    if (change > rollThreshold)
                                //    {
                                //        prevRoll = roll;
                                //        pub.SendASingleData("WII|Roll", Math.Round((double)wiiVarsTable["Roll"], 2).ToString());
                                //    }
                                //}
                        
                    }
                }
            //}
            //catch (Exception ex)
            //{
            //}
            */
        }


        private void UpdateWiiSensorState(object sender, SensorMashChangedEventArgs args)
        {
            try
            {
                wiiVars = (RawWiimoteVars)args.sensorState;
                //Dictionary<string, object> wiiVarsTable = wiiVars.varNameObjectMap;
                wiiVarsTable = wiiVars.varNameObjectMap;

                //if (this.clbButtons.InvokeRequired)
                //{
                    SetCheckListBoxCallback sclb = new SetCheckListBoxCallback(SetCheckListBox);
                    this.Invoke(sclb, new object[] { 0, clbButtons, (bool)wiiVarsTable["A"], txtWiiPrefix.Text + "A" });
                    this.Invoke(sclb, new object[] { 1, clbButtons, (bool)wiiVarsTable["B"], txtWiiPrefix.Text + "B" });
                    this.Invoke(sclb, new object[] { 2, clbButtons, (bool)wiiVarsTable["Minus"], txtWiiPrefix.Text + "Minus" });
                    this.Invoke(sclb, new object[] { 3, clbButtons, (bool)wiiVarsTable["Home"], txtWiiPrefix.Text + "Home" });
                    this.Invoke(sclb, new object[] { 4, clbButtons, (bool)wiiVarsTable["Plus"], txtWiiPrefix.Text + "Plus" });
                    this.Invoke(sclb, new object[] { 5, clbButtons, (bool)wiiVarsTable["One"], txtWiiPrefix.Text + "WIIOne" });
                    this.Invoke(sclb, new object[] { 6, clbButtons, (bool)wiiVarsTable["Two"], txtWiiPrefix.Text + "Two" });
                    this.Invoke(sclb, new object[] { 7, clbButtons, (bool)wiiVarsTable["Up"], txtWiiPrefix.Text + "Up" });
                    this.Invoke(sclb, new object[] { 8, clbButtons, (bool)wiiVarsTable["Down"], txtWiiPrefix.Text + "Down" });
                    this.Invoke(sclb, new object[] { 9, clbButtons, (bool)wiiVarsTable["Left"], txtWiiPrefix.Text + "Left" });
                    this.Invoke(sclb, new object[] { 10, clbButtons, (bool)wiiVarsTable["Right"], txtWiiPrefix.Text + "Right" });
                //}
                //else
                //{
                //    clbButtons.SetItemChecked(0, (bool)wiiVarsTable["A"]);
                //    clbButtons.SetItemChecked(1, (bool)wiiVarsTable["B"]);
                //    clbButtons.SetItemChecked(2, (bool)wiiVarsTable["Minus"]);
                //    clbButtons.SetItemChecked(3, (bool)wiiVarsTable["Home"]);
                //    clbButtons.SetItemChecked(4, (bool)wiiVarsTable["Plus"]);
                //    clbButtons.SetItemChecked(5, (bool)wiiVarsTable["One"]);
                //    clbButtons.SetItemChecked(6, (bool)wiiVarsTable["Two"]);
                //    clbButtons.SetItemChecked(7, (bool)wiiVarsTable["Up"]);
                //    clbButtons.SetItemChecked(8, (bool)wiiVarsTable["Down"]);
                //    clbButtons.SetItemChecked(9, (bool)wiiVarsTable["Left"]);
                //    clbButtons.SetItemChecked(10, (bool)wiiVarsTable["Right"]);
                //}

                //if (this.chkLED1.InvokeRequired)
                //{
                    SetCheckBoxCallback scb = new SetCheckBoxCallback(SetCheckBox);
                    this.Invoke(scb, new object[] { (bool)wiiVarsTable["LED1"], chkLED1, txtWiiPrefix.Text + "LED1" });
                //}
                //else
                //{
                //    chkLED1.Checked = (bool)wiiVarsTable["LED1"];
                //}
                //if (this.chkLED2.InvokeRequired)
                //{
                    scb = new SetCheckBoxCallback(SetCheckBox);
                    this.Invoke(scb, new object[] { (bool)wiiVarsTable["LED2"], chkLED2, "WIILED2" });
                //}
                //else
                //{
                //    chkLED2.Checked = (bool)wiiVarsTable["LED2"];
                //}
                //if (this.chkLED3.InvokeRequired)
                //{
                    scb = new SetCheckBoxCallback(SetCheckBox);
                    this.Invoke(scb, new object[] { (bool)wiiVarsTable["LED3"], chkLED3, "WIILED3" });
                //}
                //else
                //{
                //    chkLED3.Checked = (bool)wiiVarsTable["LED3"];
                //}
                //if (this.chkLED4.InvokeRequired)
                //{
                    scb = new SetCheckBoxCallback(SetCheckBox);
                    this.Invoke(scb, new object[] { (bool)wiiVarsTable["LED4"], chkLED4, "WIILED4"});
                //}
                //else
                //{
                //    chkLED1.Checked = (bool)wiiVarsTable["LED4"];
                //}

                g.Clear(Color.Black);

                string accel = string.Format("{{X={0}, Y={1}, Z={2}}}", Math.Round((double)wiiVarsTable["X"], 2), Math.Round((double)wiiVarsTable["Y"], 2), Math.Round((double)wiiVarsTable["Z"], 2));
                // Check if this method is running on a different thread
                // than the thread that created the control.
                //if (this.lblAccel.InvokeRequired)
                //{
                    // It's on a different thread, so use Invoke.
                    SetTextCallback st = new SetTextCallback(SetText);
                    this.Invoke(st, new object[] { accel, this.lblAccel });
                //}
                //else
                //{
                //    // It's on the same thread, no need for Invoke
                //    this.lblAccel.Text = accel;
                //}

                string rollPitch = string.Format("{{Roll={0}, Pitch={1}}}", Math.Round((double)wiiVarsTable["Roll"], 2), Math.Round((double)wiiVarsTable["Pitch"], 2));
                //if (this.lblRollPitch.InvokeRequired)
                //{
                    st = new SetTextCallback(SetText);
                    this.Invoke(st, new object[] { rollPitch, this.lblRollPitch });
                //}
                //else
                //{
                //    this.lblRollPitch.Text = rollPitch;
                //}

                UpdateIR((bool)wiiVarsTable["ir0Found"], (double)wiiVarsTable["ir0Size"], (double)wiiVarsTable["ir0X"], (double)wiiVarsTable["ir0Y"], (double)wiiVarsTable["irRaw0X"],
                    (double)wiiVarsTable["irRaw0Y"], lblIR1, lblIR1Raw, chkFound1, Color.Red, "WIIir0Found");
                UpdateIR((bool)wiiVarsTable["ir1Found"], (double)wiiVarsTable["ir1Size"], (double)wiiVarsTable["ir1X"], (double)wiiVarsTable["ir1Y"], (double)wiiVarsTable["irRaw1X"],
                    (double)wiiVarsTable["irRaw1Y"], lblIR2, lblIR2Raw, chkFound2, Color.Blue, "WIIir1Found");
                UpdateIR((bool)wiiVarsTable["ir2Found"], (double)wiiVarsTable["ir2Size"], (double)wiiVarsTable["ir2X"], (double)wiiVarsTable["ir2Y"], (double)wiiVarsTable["irRaw2X"],
                    (double)wiiVarsTable["irRaw2Y"], lblIR3, lblIR3Raw, chkFound3, Color.Yellow, "WIIir3Found");
                UpdateIR((bool)wiiVarsTable["ir3Found"], (double)wiiVarsTable["ir3Size"], (double)wiiVarsTable["ir3X"], (double)wiiVarsTable["ir3Y"], (double)wiiVarsTable["irRaw3X"],
                    (double)wiiVarsTable["irRaw3Y"], lblIR4, lblIR4Raw, chkFound4, Color.Orange, "WIIir3Found");

                pbIR.Image = b;

                double batt = (double)wiiVarsTable["Battery"];

                //if (this.pbBattery.InvokeRequired)
                //{
                    SetProgressBarCallback spb = new SetProgressBarCallback(SetProgressBar);
                    this.Invoke(spb, new object[] { (int)batt });
                //}
                //else
                //{
                //    pbBattery.Value = (batt > 0xc8 ? 0xc8 : (int)batt);
                //}

                // Check if this method is running on a different thread
                // than the thread that created the control.
                //if (this.lblBattery.InvokeRequired)
                //{
                    // It's on a different thread, so use Invoke.
                    st = new SetTextCallback(SetText);
                    this.Invoke(st, new object[] { batt.ToString(), this.lblBattery });
                //}
                //else
                //{
                //    // It's on the same thread, no need for Invoke
                //    lblBattery.Text = batt.ToString();
                //}

                //if (wiiVarsTable["ExtensionType"] != null)
                //{
                //    if (this.chkExtension.InvokeRequired)
                //    {
                        SetCboTextCallback scbt = new SetCboTextCallback(SetCboText);
                        this.Invoke(scbt, new object[] { wiiVarsTable["ExtensionType"].ToString(), chkExtension, "WIIExtensionType" });
                        SetCheckBoxCallback scbo = new SetCheckBoxCallback(SetCheckBox);
                        this.Invoke(scbo, new object[] { wiiVarsTable["ExtensionInserted"], chkExtension, "WIIExtensionInserted" });
                    //}
                    //else
                    //{
                    //    chkExtension.Text = wiiVarsTable["ExtensionType"].ToString();
                    //    chkExtension.Checked = (bool)wiiVarsTable["ExtensionInserted"];
                    //}

                    if ((string)wiiVars.varNameObjectMap["ExtensionType"] == "Nunchuk")
                    {
                        string NunAccel = string.Format("{{X={0}, Y={1}, Z={2}}}",
                            Math.Round((double)wiiVarsTable["NunXAcc"], 2), Math.Round((double)wiiVarsTable["NunYAcc"], 2), Math.Round((double)wiiVarsTable["NunZAcc"], 2));
                        //if (this.lblChuk.InvokeRequired)
                        //{
                            SetTextCallback stc = new SetTextCallback(SetText);
                            this.Invoke(stc, new object[] { NunAccel, lblChuk });
                        //}
                        //else
                        //{
                        //    lblChuk.Text = NunAccel;
                        //}

                        string joys = string.Format("{{X={0}, Y={1}}}", Math.Round((double)wiiVarsTable["NunXJoystick"], 2), Math.Round((double)wiiVarsTable["NunYJoystick"], 2));
                        //if (this.lblChukJoy.InvokeRequired)
                        //{
                            //SetTextCallback stc = new SetTextCallback(SetText);
                            this.Invoke(stc, new object[] { joys, lblChukJoy });
                        //}
                        //else
                        //{
                        //    lblChukJoy.Text = joys;
                        //}

                        string NunRollPitch = string.Format("{{Roll={0}, Pitch={1}}}", Math.Round((double)wiiVarsTable["NunRoll"], 2), Math.Round((double)wiiVarsTable["NunPitch"], 2));
                        //if (this.lblNunRollPitch.InvokeRequired)
                        //{
                        //    SetTextCallback st = new SetTextCallback(SetText);
                            this.Invoke(st, new object[] { NunRollPitch, this.lblNunRollPitch });
                        //}
                        //else
                        //{
                        //    this.lblNunRollPitch.Text = NunRollPitch;
                        //}

                        //if (this.chkC.InvokeRequired)
                        //{
                        //    SetCheckBoxCallback scb = new SetCheckBoxCallback(SetCheckBox);
                            this.Invoke(scb, new object[] { (bool)wiiVarsTable["NunC"], chkC });
                        //}
                        //else
                        //{
                        //    chkC.Checked = (bool)wiiVarsTable["NunC"];
                        //}

                        //if (this.chkZ.InvokeRequired)
                        //{
                        //    SetCheckBoxCallback scb = new SetCheckBoxCallback(SetCheckBox);
                            this.Invoke(scb, new object[] { (bool)wiiVarsTable["NunZ"], chkZ });
                        //}
                        //else
                        //{
                        //    chkZ.Checked = (bool)wiiVarsTable["NunZ"];
                        //}
                    }
                //}
            //    if (isStreaming)
            //    {
            //        //foreach (KeyValuePair<string, object> kvp in wiiVarsTable)
            //        //{
            //        //    if (kvp.Value != null)
            //        //        pub.SendASingleData("WII" + kvp.Key, kvp.Value.ToString());
            //        //}

            //        double roll = Math.Round((double)wiiVarsTable["Roll"], 2);
            //        double change = Math.Abs(Math.Abs(roll) - Math.Abs(prevRoll));

            //        if (change > rollThreshold)
            //        {
            //            prevRoll = roll;
            //            pub.SendASingleData("WIIRoll", Math.Round((double)wiiVarsTable["Roll"], 2).ToString());                        
            //        }
                    
            //        pub.SendASingleData("WIIPitch", Math.Round((double)wiiVarsTable["Pitch"], 2).ToString());
            //        pub.SendASingleData("WIIX", Math.Round((double)wiiVarsTable["X"], 2).ToString());
            //        pub.SendASingleData("WIIY", Math.Round((double)wiiVarsTable["Y"], 2).ToString());
            //        pub.SendASingleData("WIIZ", Math.Round((double)wiiVarsTable["Z"], 2).ToString());
            //    }
            }
            catch (ObjectDisposedException ode)
            {
                Console.WriteLine("Exception: " + ode.Message);
                //this.Close();
            }
        }

        //private void UpdateNunchukSensorState(object sender, SensorMashChangedEventArgs args)
        //{
        //    try
        //    {
        //        //if (wiiVars.varNameObjectMap["ExtensionType"] != null && ((int)wiiVars.varNameObjectMap["ExtensionType"] == 0xfefe))
        //        //{
        //        nunchukVars = (RawNunchukVars)args.sensorState;
        //        if (nunchukVars != null)
        //        {
        //            string accel = string.Format("{{X={0}, Y={1}, Z={2}}}",
        //                Math.Round((double)nunchukVars.varNameObjectMap["XAcc"], 2), Math.Round((double)nunchukVars.varNameObjectMap["YAcc"], 2), Math.Round((double)nunchukVars.varNameObjectMap["ZAcc"], 2));
        //            if (this.lblChuk.InvokeRequired)
        //            {
        //                SetTextCallback stc = new SetTextCallback(SetText);
        //                this.Invoke(stc, new object[] { accel, lblChuk });
        //            }
        //            else
        //            {
        //                lblChuk.Text = accel;
        //            }

        //            string joys = string.Format("{{X={0}, Y={1}}}", Math.Round((double)nunchukVars.varNameObjectMap["XJoystick"], 2), Math.Round((double)nunchukVars.varNameObjectMap["YJoystick"], 2));
        //            if (this.lblChukJoy.InvokeRequired)
        //            {
        //                SetTextCallback stc = new SetTextCallback(SetText);
        //                this.Invoke(stc, new object[] { joys, lblChukJoy });
        //            }
        //            else
        //            {
        //                lblChukJoy.Text = joys;
        //            }

        //            string rollPitch = string.Format("{{Roll={0}, Pitch={1}}}", Math.Round((double)nunchukVars.varNameObjectMap["Roll"], 2), Math.Round((double)nunchukVars.varNameObjectMap["Pitch"], 2));
        //            if (this.lblNunRollPitch.InvokeRequired)
        //            {
        //                SetTextCallback st = new SetTextCallback(SetText);
        //                this.Invoke(st, new object[] { rollPitch, this.lblNunRollPitch });
        //            }
        //            else
        //            {
        //                this.lblNunRollPitch.Text = rollPitch;
        //            }

        //            if (this.chkC.InvokeRequired)
        //            {
        //                SetCheckBoxCallback scb = new SetCheckBoxCallback(SetCheckBox);
        //                this.Invoke(scb, new object[] { (bool)nunchukVars.varNameObjectMap["C"], chkC });
        //            }
        //            else
        //            {
        //                chkC.Checked = (bool)nunchukVars.varNameObjectMap["C"];
        //            }

        //            if (this.chkZ.InvokeRequired)
        //            {
        //                SetCheckBoxCallback scb = new SetCheckBoxCallback(SetCheckBox);
        //                this.Invoke(scb, new object[] { (bool)nunchukVars.varNameObjectMap["Z"], chkZ });
        //            }
        //            else
        //            {
        //                chkZ.Checked = (bool)nunchukVars.varNameObjectMap["Z"];
        //            }
        //        }
        //    }
        //    catch (ObjectDisposedException ode)
        //    {
        //        Console.WriteLine("Exception: " + ode.Message);
        //        //this.Close();
        //    }
        //}

        private void UpdateIR(bool irFound, double irSize, double posX, double posY, double rawPositionX, double rawPositionY, 
            Label lblNorm, Label lblRaw, CheckBox chkFound, Color color, string irFoundVarname)
        {
            if (chkFound.InvokeRequired)
            {
                SetCheckBoxCallback scb = new SetCheckBoxCallback(SetCheckBox);
                this.Invoke(scb, new object[] { irFound, chkFound, irFoundVarname });
            }
            else
            {
                chkFound.Checked = irFound;
            }
                   

            if (irFound)
            {
                string s = "X: " + Math.Round(posX,2) + ", Y: " + Math.Round(posY,2) + ". Size=" + irSize;
                string sRaw = "X: " + Math.Round(rawPositionX,2) + ", Y: " + Math.Round(rawPositionY);

                if (lblNorm.InvokeRequired)
                {
                    // It's on a different thread, so use Invoke.
                    SetTextCallback st = new SetTextCallback(SetText);
                    this.Invoke(st, new object[] { s, lblNorm });
                }
                else
                {
                    lblNorm.Text = s;
                }

                if (lblRaw.InvokeRequired)
                {
                    // It's on a different thread, so use Invoke.
                    SetTextCallback st = new SetTextCallback(SetText);
                    this.Invoke(st, new object[] { sRaw, lblRaw });
                }
                else
                {
                    lblRaw.Text = sRaw;
                }

                
                g.DrawEllipse(new Pen(color), (int)(rawPositionX / 4), (int)(rawPositionY / 4), (int) irSize + 1, (int) irSize + 1);
            }
        }

        // This method is passed in to the SetTextCallBack delegate to set the Text property of ComboBox cbo
        private void SetCboText(string text, CheckBox cbo, string varName)
        {
            if (cbo.Text != text)
            {
                cbo.Text = text;
                if (isStreaming)
                    pub.SendASingleData(varName, text);
            }
            
        }

        // This method is passed in to the SetCheckCallBack delegate
        private void SetCheckBox(bool check, CheckBox cbo, string varName)
        {
            if (cbo.Checked != check)
            {
                cbo.Checked = check;
                if (isStreaming)
                    pub.SendASingleData(varName, check.ToString());
            }
        }

        // This method is passed in to the SetCheckListCallBack delegate
        private void SetCheckListBox(int pos, CheckedListBox clbo, bool check, string varName)
        {
            if (clbo.GetItemChecked(pos) != check)
            {
                clbo.SetItemChecked(pos, check);
                if (isStreaming)
                    pub.SendASingleData(varName, check.ToString());
            }
        }

        // This method is passed in to the SetProgressBarCallBack delegate
        private void SetProgressBar(int val)
        {
            pbBattery.Value = (val > 0xc8 ? 0xc8 : val);
        }


        // This method is passed in to the SetTextCallBack delegate to set the Text property of Label lbl
        private void SetText(string text, Label lbl)
        {
            //if (lbl.Text != text)
            //{
            lbl.Text = text;
            //    pub.SendASingleData(varName, text);
            //}
        }

        // This method is passed in to the SetTextCallBack delegate to set the Text property of Label lbl
        private void SetTextBox(string text, TextBox txtbox)
        {
            txtbox.Text = text;
        }

        private void UI_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (wiiD != null)
            {
                wiiD.DisconnectWiimote();
            }
        }

        private void btnOpenPort_Click(object sender, EventArgs e)
        {
            if (txtPortName.Text != null || txtPortName.Text != "")
            {
                portName = txtPortName.Text;
            }
            serialPort = new SerialPort(portName, baudRate, Parity.None, 8, StopBits.One);
            serialPort.DataReceived += comPort_DataReceived;
            if (!serialPort.IsOpen)
            {                
                serialPort.DtrEnable = true;
                serialPort.Open();          
            }
        }

        /// <summary>
        /// method that will be called when theres data waiting in the buffer
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if (e.EventType == SerialData.Chars)
            {
                string msg = serialPort.ReadLine();

                ProcessArduinoData(msg);
            }
        }

        private void ProcessArduinoData(string message)
        {
            if (message.Contains("light:"))
            {
                string data = message.Substring(message.IndexOf(":")+1);
                pub.SendASingleData("ARDLIGHT", data);
                if (this.txtLight.InvokeRequired)
                {
                    SetTextBoxCallback st = new SetTextBoxCallback(SetTextBox);
                    this.Invoke(st, new object[] { data, this.txtLight });
                }
                else
                {
                    this.txtLight.Text = data;
                }
            }
            else if (message.Contains("sound:"))
            {
                string data = message.Substring(message.IndexOf(":") + 1);
                pub.SendASingleData("ARDSOUND", data);
                if (this.txtSound.InvokeRequired)
                {
                    SetTextBoxCallback st = new SetTextBoxCallback(SetTextBox);
                    this.Invoke(st, new object[] { data, this.txtSound });
                }
                else
                {
                    this.txtSound.Text = data;
                }
            }
            else
            {
                if (message != null && message != "" && message.Contains(":"))
                {
                    string data = message.Substring(message.IndexOf(":") + 1);
                    pub.SendASingleData(message.Substring(0, message.IndexOf(":")), data);
                    if (this.txtOtherData.InvokeRequired)
                    {
                        SetTextBoxCallback st = new SetTextBoxCallback(SetTextBox);
                        this.Invoke(st, new object[] { message.Substring(0, message.IndexOf(":")) + ":" + data, this.txtOtherData });
                    }
                    else
                    {
                        if (this.txtOtherData.Lines.Length > 5)
                            this.txtOtherData.Clear();
                        this.txtOtherData.AppendText(message.Substring(0, message.IndexOf(":")) + ":" + data);
                    }
                }
            }
        }

        private void btnConnectWii_Click(object sender, EventArgs e)
        {
            wiiD = new WiimoteData();
            g = Graphics.FromImage(b);
            wiiD.WiiSensorChanged += UpdateWiiSensorState;
            //wiiD.NunchukSensorChanged += UpdateNunchukSensorState;  
        }

        private void btnStartPublishing_Click(object sender, EventArgs e)
        {
            if (!isStreaming)
            {
                pub = new Publisher(txtIP.Text, Convert.ToInt32(txtPortNo.Text));

                isStreaming = true;
                btnStartPublishing.Text = "Stop Publishing";
                timer.Enabled = true;
                timedStreaming = true;
            }
            else
            {
                isStreaming = false;
                btnStartPublishing.Text = "Start Publishing";
                timer.Enabled = false;
                timedStreaming = false;
            }
        }

        private void chkPubButtons_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void chkPubAccel_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void chkPubIR_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void chkPubRollPitch_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void chkPubBattery_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void chkPubNunchuk_CheckedChanged(object sender, EventArgs e)
        {

        }
    }
}
